package org.admin.entity.dto;

import core.validate.Rule;
import lombok.Getter;
import lombok.Setter;
import org.admin.entity.BaseDto;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.HashMap;
import java.util.Objects;

@Setter
public class FileDto extends BaseDto<FileDto> {
    public enum HEADERS {
        JPEG("JPEG", "FFD8FF"),
        PNG("PNG", "89504E47"),
        GIF("GIF", "47494638"),
        TIFF("TIFF", "49492A00"),
        BMP("BMP", "424D"),
        DWG("DWG", "41433130"),
        PSD("PSD", "38425053"),
        RTF("RTF", "7B5C727466"),
        XML("XML", "3C3F786D6C"),
        HTML("HTML", "68746D6C3E"),
        DBX("DBX", "CFAD12FEC5FD746F"),
        PST("PST", "2142444E"),
        OLE2("OLE2", "0xD0CF11E0A1B11AE1"),
        XLS_DOC("XLS_DOC", "D0CF11E0"),
        MDB("MDB", "5374616E64617264204A"),
        WPB("WPB", "FF575043"),
        EPS_PS("EPS_PS", "252150532D41646F6265"),
        PDF("PDF", "255044462D312E"),
        PWL("PWL", "E3828596"),
        ZIP("ZIP", "504B0304"),
        RAR("RAR", "52617221"),
        WAV("WAV", "57415645"),
        AVI("AVI", "41564920"),
        RAM("RAM", "2E7261FD"),
        RM("RM", "2E524D46"),
        MOV("MOV", "6D6F6F76"),
        ASF("ASF", "3026B2758E66CF11"),
        MID("MID", "4D546864");

        private final String key;
        private final String value;

        HEADERS(String key, String value) {
            this.key = key;
            this.value = value;
        }
        public String getValue(){
            return value.toLowerCase();
        }
        public String getKey(){
            return key.toLowerCase();
        }
    };
    protected FileDto inst(){
        return this;
    }
    @Getter
    private MultipartFile file;
    private Integer width;
    private Integer height;
    private Integer top;
    private Integer left;
    private Integer right;
    private Integer bottom;

    private Boolean center;
    private Integer rotate;
    private Integer flip;
    private Double quality;
    @Getter
    private Integer current;
    private Integer size;
    private Integer type;
    public FileDto(){
        /*
        "*file", "width", "height", "top", "left", "right",
                "bottom", "type", "rotate", "flip", "quality",
         */
        addRule(new Rule<?>[] {
                Rule.File("file").test(holder -> {
                    MultipartFile file = holder.getValue();
                    return !file.isEmpty();
                }, "上传文件不能为空").test(holder -> {
                    MultipartFile file = holder.getValue();
                    try (java.io.InputStream inputStream = file.getInputStream()) {
                        byte[] buffer = new byte[28];
                        if(inputStream.read(buffer) < 6) return false;
                        StringBuilder stringBuilder = new StringBuilder();
                        for (byte buf : buffer) {
                            int v = buf & 0xFF;
                            String hv = Integer.toHexString(v);
                            if (hv.length() < 2) {
                                stringBuilder.append(0);
                            }
                            stringBuilder.append(hv);
                        }
                        String header = stringBuilder.toString();
                        return header.startsWith(HEADERS.JPEG.getValue())
                                || header.startsWith(HEADERS.PNG.getValue());
                    }catch (IOException e) {
                        return false;
                    }
                }, "未知格式"),
                Rule.Number("quality")
                        .between(0, 1, "图像压缩系数不正确"),
                Rule.Boolean("center")
                        .setMessages("缩放模式不正确"),
                Rule.Number("type")
                        .between(0, 2, "查询文件格式不正确"),
                Rule.Number("current")
                        .min(1, "当前分页错误"),
                Rule.Number("size")
                        .onPreCheck(val -> Objects.requireNonNullElse(val, 20))
                        .min(1, "分页数量错误")
        }).addRule(Rule.<String>NumberGroup(new HashMap<>(){{
            put("width", "图像宽度");
            put("height", "图像高度");
            put("top", "图像顶部裁切距离");
            put("left", "图像左侧裁切距离");
            put("right", "图像右侧裁切距离");
            put("bottom", "图像底部裁切举例");
            //"type", "rotate", "flip", "quality",
        }}, (rule, title) -> {
            rule.min(0, title + "溢出");
        }).toArray(
                new Rule<?>[0])
        ).addRule(Rule.<String>NumberGroup(new HashMap<>(){{
            put("rotate", "图像旋转系数");
            put("flip", "图像镜像系数");
        }}, (rule, title) -> {
            // 整数判断
            rule.test(holder -> {
                Object value = holder.getValue();
                String strVal = value.toString();
                return strVal.matches("^-?\\d+$");
            },title +"格式不正确");
        }).toArray(new Rule<?>[0]));
    }

    public int getWidth(){
        return width == null ? 0 : width;
    }

    public int getHeight(){
        return height == null ? 0 : height;
    }

    public int getTop(){
        return top == null ? 0 : top;
    }

    public int getLeft(){
        return left == null ? 0 : left;
    }
    public int getRight(){
        return right == null ? 0 : right;
    }
    public int getBottom(){
        return bottom == null ? 0 : bottom;
    }

    public boolean getCenter() {
        return center == null || center;
    }

    public int getRotate(){
        return rotate == null ? 0 : rotate;
    }

    public int getFlip(){
        return flip == null ? 0 : flip;
    }

    public double getQuality(){
        return quality == null ? 0f: quality;
    }

    public int getSize(){
        return size == null ? 20: size;
    }
    public int getType(){
        return type == null ? 0: type;
    }
}
